home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c-part1 / 3197 < prev    next >
Encoding:
Text File  |  1996-08-05  |  4.6 KB  |  242 lines

  1. Path: unix.sri.com!usenet
  2. From: mklenk@updike.sri.com (Mark Klenk)
  3. Newsgroups: comp.lang.c
  4. Subject: Re: garbage collection and C (not C++!)
  5. Date: 26 Jan 1996 22:14:22 GMT
  6. Organization: SRI International
  7. Message-ID: <4ebjnu$424@unix.sri.com>
  8. References: <4e4bc5$c5f@ns.RezoNet.NET>
  9. Reply-To: mklenk@updike.sri.com
  10. NNTP-Posting-Host: 204.75.161.40
  11.  
  12.  
  13. Ray Dunn:
  14. >
  15. >I think we'd all be interested in this.  Post it.
  16.  
  17.     Ok, you asked for it - here it is.
  18.  
  19. --- gc.h ---
  20. /*
  21.  *    FILE:     gc.h                LANGUAGE: ANSI C
  22.  *
  23.  *    AUTHOR:   Mark Klenk          DATE: 12/22/94
  24.  *
  25.  *    PURPOSE:  Definition of a garbage collection interface.
  26.  */
  27.  
  28. #ifndef __GC_H__
  29. #define __GC_H__
  30.  
  31. #include <stdlib.h>                     /* size_t */
  32.  
  33. #ifndef GC_DISABLE
  34. #define malloc(size)            gc_malloc(size)
  35. #define calloc(num, size)       gc_calloc(num, size)
  36. #define realloc(ptr, size)      gc_realloc(ptr, size, __FILE__, __LINE__)
  37. #define free(ptr)               gc_free(ptr, __FILE__, __LINE__)
  38. #endif
  39.  
  40. void *  gc_malloc   (size_t size);
  41. void *  gc_calloc   (size_t num, size_t size);
  42. void *  gc_realloc  (void * ptr, size_t size, char const * filename, int line);
  43. void    gc_free     (void * ptr, char const * filename, int line);
  44.  
  45. #endif
  46.  
  47. --- gc.c ---
  48. /*
  49.  *    FILE:     gc.c                LANGUAGE: ANSI C
  50.  *
  51.  *    AUTHOR:   Mark Klenk          DATE: 12/22/94
  52.  *
  53.  *    PURPOSE:  Implementation of a garbage collection interface.
  54.  */
  55.  
  56. #include <signal.h>
  57. #include <stdio.h>
  58. #include <stdlib.h>
  59. #include "gc.h"
  60.  
  61. #undef malloc
  62. #undef calloc
  63. #undef realloc
  64. #undef free
  65.  
  66.  
  67. typedef struct _GC_Node GC_Node;
  68.  
  69. struct _GC_Node {
  70.     GC_Node *   next;
  71.     void *      ptr;
  72.     size_t      size;
  73. };
  74.  
  75.  
  76. static GC_Node  gc_heap = {NULL, NULL, 0};
  77.  
  78.  
  79. static void gc_exit_cleanup(void)
  80. {
  81.     GC_Node *   curr;
  82.  
  83.     while ((curr = gc_heap.next) != &gc_heap) {
  84.         gc_heap.next = curr->next;
  85.         free(curr->ptr);
  86.         free(curr);
  87.     }
  88. }
  89.  
  90.  
  91. static void gc_signal_handler(int signal_no)
  92. {
  93.     signal(SIGINT, gc_signal_handler);  /* Make sure we catch another CTRL-C. */
  94.     gc_exit_cleanup();
  95.     signal(SIGINT, SIG_DFL);            /* Restore the interrupt handler. */
  96.     raise(signal_no);                   /* Wake up default handler. */
  97. }
  98.  
  99.  
  100. static void gc_initialize(void)
  101. {
  102.     if (NULL == gc_heap.next) {
  103.         gc_heap.next = &gc_heap;
  104.         atexit(gc_exit_cleanup);
  105.         signal(SIGINT, gc_signal_handler);
  106.         signal(SIGABRT, gc_signal_handler);
  107.     }
  108. }
  109.  
  110.  
  111. static GC_Node * gc_find_node(void * ptr)
  112. {
  113.     GC_Node *   prev;
  114.  
  115.     for (prev = &gc_heap; prev->next != &gc_heap; prev = prev->next) {
  116.         if (prev->next->ptr == ptr) {
  117.             return prev;
  118.         }
  119.     }
  120.  
  121.     return NULL;
  122. }
  123.  
  124.  
  125. static void gc_error(void * ptr, char const * filename, int line)
  126. {
  127.     fprintf(stderr, "Garbage collector caught invalid pointer %p in %s: %d.\n",
  128.             ptr, filename, line);
  129.     abort();
  130. }
  131.  
  132.  
  133. void * gc_malloc(size_t size)
  134. {
  135.     GC_Node *   node;
  136.  
  137.     gc_initialize();
  138.  
  139.     node = malloc(sizeof(GC_Node));
  140.     if (NULL == node) {
  141.         return NULL;
  142.     }
  143.  
  144.     node->ptr = malloc(size);
  145.     if (NULL == node->ptr) {
  146.         free(node);
  147.         return NULL;
  148.     }
  149.  
  150.     node->size = size;
  151.     node->next = gc_heap.next;
  152.     gc_heap.next = node;
  153.  
  154.     return node->ptr;
  155. }
  156.  
  157.  
  158. void * gc_calloc(size_t num, size_t size)
  159. {
  160.     GC_Node *   node;
  161.  
  162.     gc_initialize();
  163.  
  164.     node = malloc(sizeof(GC_Node));
  165.     if (NULL == node) {
  166.         return NULL;
  167.     }
  168.  
  169.     node->ptr = calloc(num, size);
  170.     if (NULL == node->ptr) {
  171.         free(node);
  172.         return NULL;
  173.     }
  174.  
  175.     node->size = size * num;
  176.     node->next = gc_heap.next;
  177.     gc_heap.next = node;
  178.  
  179.     return node->ptr;
  180. }
  181.  
  182.  
  183. void * gc_realloc(void * ptr, size_t size, char const * filename, int line)
  184. {
  185.     GC_Node *   node;
  186.  
  187.     gc_initialize();
  188.  
  189.     if (NULL == ptr) {
  190.         return gc_malloc(size);         /* Create it if it doesn't exist. */
  191.     }
  192.  
  193.     node = gc_find_node(ptr);
  194.     if (NULL == node) {
  195.         gc_error(ptr, filename, line);  /* This means 'ptr' is invalid. */
  196.     }
  197.     node = node->next;                  /* Point to actual node, not prev. */
  198.  
  199.     ptr = realloc(ptr, size);
  200.     if (NULL == ptr) {
  201.         return NULL;
  202.     }
  203.  
  204.     node->ptr = ptr;
  205.     node->size = size;
  206.  
  207.     return ptr;
  208. }
  209.  
  210.  
  211. void gc_free(void * ptr, char const * filename, int line)
  212. {
  213.     GC_Node *   curr;
  214.     GC_Node *   prev;
  215.  
  216.     gc_initialize();
  217.  
  218.     if (NULL == ptr) {
  219.         return;
  220.     }
  221.  
  222.     prev = gc_find_node(ptr);
  223.     if (NULL == prev) {
  224.         gc_error(ptr, filename, line);  /* This means 'ptr' is invalid. */
  225.     }
  226.  
  227.     curr = prev->next;
  228.     prev->next = curr->next;
  229.  
  230.     free(curr->ptr);
  231.     free(curr);
  232. }
  233.  
  234.  
  235.  
  236. ---
  237.  
  238. mklenk@coronacorp.com       (Mark Klenk)
  239.  
  240.  
  241.  
  242.